<?php
// +---------------------------------------------------------------------+
// | OneBase    | [ WE CAN DO IT JUST THINK ]                            |
// +---------------------------------------------------------------------+
// | Licensed   | http://www.apache.org/licenses/LICENSE-2.0 )           |
// +---------------------------------------------------------------------+
// | Author     | 王勇程 <laughskydragon@qq.com>                         |
// +---------------------------------------------------------------------+
// | Repository | https://gitee.com/Bigotry/OneBase                      |
// +---------------------------------------------------------------------+

namespace app\api\logic;

use app\common\logic\User as CommonUser;
use app\api\error\CodeBase;
use app\api\error\Common;

/**
 * 微信小程序接口逻辑
 */
class Wechat extends ApiBase
{
    
    public static $commonUserLogic = null;
    
    /**
     * 基类初始化
     */
    public function __construct()
    {
        // 执行父类构造方法
        parent::__construct();
        
        empty(static::$commonUserLogic) && static::$commonUserLogic = new CommonUser();
    }
    
    /**
     * 微信登录
     */
    public function wechatLogin($data = [])
    {
        try {
            $code = $data['code'] ?? '';
            $inviterId = intval($data['inviter_id'] ?? 0);
            
            if (empty($code)) {
                return [RESULT_ERROR, '微信授权码不能为空'];
            }
            
            // 通过微信API获取用户信息
            $wechatResult = $this->getUserInfoByCode($code);
            if ($wechatResult['code'] != 1) {
                return [RESULT_ERROR, $wechatResult['msg']];
            }
            
            $wechatInfo = $wechatResult['data'];
            
            // 检查用户是否已存在
            $user = $this->modelUser->getInfo(['openid' => $wechatInfo['openid']]);
            
            if ($user) {
                // 用户已存在，更新登录信息
                $this->modelUser->updateInfo(['id' => $user['id']], [
                    'last_login_time' => time(),
                    'last_login_ip' => $this->getClientIp(),
                    'update_time' => time()
                ]);
                
                // 检测并更新VIP状态
                static::$commonUserLogic->checkAndUpdateVipStatus($user['id']);
                
                // 重新获取用户信息（可能已更新VIP状态）
                $user = $this->modelUser->getInfo(['id' => $user['id']]);
                
                // 签发JWT token
                $tokenData = \app\api\logic\Common::userTokenSign($user);
                
                $userInfo = static::$commonUserLogic->getUserInfo(['user_id' => $user['id']]);
                if (is_array($userInfo) && !isset($userInfo[0])) {
                    $userInfo['user_token'] = $tokenData['user_token'];
                    return [RESULT_SUCCESS, '登录成功', $userInfo];
                }
                
                return [RESULT_SUCCESS, '登录成功', array_merge($userInfo, ['user_token' => $tokenData['user_token']])];
            } else {
                // 新用户注册
                return $this->registerUser($wechatInfo, $inviterId);
            }
            
        } catch (\Exception $e) {
            return [RESULT_ERROR, '微信登录异常：' . $e->getMessage()];
        }
    }
    
    /**
     * 获取客户端IP
     */
    private function getClientIp()
    {
        if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
            return $_SERVER['HTTP_CLIENT_IP'];
        } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            return $_SERVER['HTTP_X_FORWARDED_FOR'];
        } else {
            return $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1';
        }
    }
    
    /**
     * 注册新用户
     */
    private function registerUser($wechatInfo, $inviterId = 0)
    {
        try {
            // 校验邀请人ID
            if ($inviterId > 0) {
                $inviter = $this->modelUser->getInfo(['id' => $inviterId]);
                if (empty($inviter)) {
                    $inviterId = 0;
                }
            }
            
            // 生成邀请码
            $inviteCodeNew = static::$commonUserLogic->generateInviteCode();
            
            // 创建用户
            $userData = [
                'openid' => $wechatInfo['openid'],
                'unionid' => $wechatInfo['unionid'] ?? '',
                'nickname' => '微信用户',
                'avatar_url' => '',
                'gender' => 0,
                'invite_code' => $inviteCodeNew,
                'inviter_id' => $inviterId,
                'vip_level' => 0,
                'vip_expire_time' => 0,
                'total_points' => 0,
                'total_earnings' => 0,
                'status' => 1,
                'last_login_time' => time(),
                'last_login_ip' => $this->getClientIp(),
                'create_time' => time(),
                'update_time' => time()
            ];
            
            $userId = $this->modelUser->setInfo($userData);
            
            if ($userId) {
                // 新用户注册奖励
                $this->giveRegisterReward($userId);
                
                // 邀请奖励
                if ($inviterId > 0) {
                    $this->giveInviteReward($inviterId, $userId);
                }
                
                // 获取新注册的用户信息并签发JWT token
                $newUser = $this->modelUser->getInfo(['id' => $userId]);
                $tokenData = \app\api\logic\Common::userTokenSign($newUser);
                
                $userInfo = static::$commonUserLogic->getUserInfo(['user_id' => $userId]);
                $userInfo['user_token'] = $tokenData['user_token'];
                
                return [RESULT_SUCCESS, '注册成功', $userInfo];
            }
            
            return [RESULT_ERROR, '注册失败'];
            
        } catch (\Exception $e) {
            return [RESULT_ERROR, '注册异常：' . $e->getMessage()];
        }
    }
    
    /**
     * 新用户注册奖励
     */
    private function giveRegisterReward($userId)
    {
        try {
            // 赠送注册积分
            $this->modelUser->updateInfo(['id' => $userId], [
                'total_points' => 100,
                'update_time' => time()
            ]);
            
            // 记录积分
            $this->modelPointsRecord->setInfo([
                'user_id' => $userId,
                'type' => 'reward',
                'points' => 100,
                'description' => '新用户注册奖励',
                'create_time' => time(),
                'update_time' => time()
            ]);
            
            // 发送欢迎消息
            $this->modelMessage->setInfo([
                'user_id' => $userId,
                'type' => 'system',
                'title' => '欢迎加入亦通查',
                'content' => '恭喜您成功注册，获得100积分奖励！快来体验我们的服务吧~',
                'is_read' => 0,
                'create_time' => time(),
                'update_time' => time()
            ]);
            
        } catch (\Exception $e) {
            // 记录日志但不影响注册流程
            \think\facade\Log::error('新用户注册奖励失败：' . $e->getMessage());
        }
    }
    
    /**
     * 邀请奖励
     */
    private function giveInviteReward($inviterId, $newUserId)
    {
        try {
            // 获取邀请者当前积分
            $inviter = $this->modelUser->getInfo(['id' => $inviterId]);
            if ($inviter) {
                // 邀请者获得积分奖励
                $newPoints = $inviter['total_points'] + 200;
                $this->modelUser->updateInfo(['id' => $inviterId], [
                    'total_points' => $newPoints,
                    'update_time' => time()
                ]);
                
                // 记录积分
                $this->modelPointsRecord->setInfo([
                    'user_id' => $inviterId,
                    'type' => 'reward',
                    'points' => 200,
                    'description' => '邀请新用户奖励',
                    'related_id' => $newUserId,
                    'create_time' => time(),
                    'update_time' => time()
                ]);
                
                // 发送邀请成功消息
                $this->modelMessage->setInfo([
                    'user_id' => $inviterId,
                    'type' => 'promotion',
                    'title' => '邀请成功',
                    'content' => '恭喜您成功邀请新用户，获得200积分奖励！',
                    'extra_data' => json_encode(['invited_user_id' => $newUserId]),
                    'is_read' => 0,
                    'create_time' => time(),
                    'update_time' => time()
                ]);
            }
            
        } catch (\Exception $e) {
            // 记录日志但不影响注册流程
            \think\facade\Log::error('邀请奖励失败：' . $e->getMessage());
        }
    }

    /**
     * 微信小程序一键登录
     */
    public function miniProgramLogin($data = [])
    {
        // 验证参数
        $this->validateWechat->scene('mini_login')->check($data);
        
        // 调用微信登录逻辑
        $result = $this->wechatLogin($data);
        
        return $result;
    }

    /**
     * 获取微信小程序用户信息
     */
    public function getMiniProgramUserInfo($data = [])
    {
        // 验证参数
        $this->validateWechat->scene('get_info')->check($data);
        
        // JWT解析获取user_id
        $token = $data['user_token'] ?? '';
        if (!empty($token)) {
            $userData = get_user_by_token($token);
            $data['user_id'] = $userData['user_id'];
        }
        
        // 调用common层业务逻辑
        return static::$commonUserLogic->getMiniProgramUserInfo($data);
    }

    /**
     * 微信小程序授权手机号
     */
    public function authMobileByMiniProgram($data = [])
    {
        // 验证参数
        $this->validateWechat->scene('auth_mobile')->check($data);
        
        // JWT解析获取user_id
        $token = $data['user_token'] ?? '';
        if (!empty($token)) {
            $userData = get_user_by_token($token);
            $data['user_id'] = $userData['user_id'];
        }
        
        // 调用common层业务逻辑
        return static::$commonUserLogic->authMobileByMiniProgram($data);
    }
    
    /**
     * 通过code获取用户信息
     * @author 王勇程 <laughskydragon@qq.com>
     */
    private function getUserInfoByCode($code)
    {
        try {
            $appid = config('wechat.appid');
            $secret = config('wechat.secret');
            
            // 第一步：通过code获取access_token和openid
            $url = "https://api.weixin.qq.com/sns/jscode2session?appid={$appid}&secret={$secret}&js_code={$code}&grant_type=authorization_code";
            $result = $this->httpGet($url);
            $data = json_decode($result, true);
            
            if (isset($data['errcode'])) {
                return ['code' => 0, 'msg' => '微信授权失败：' . $data['errmsg']];
            }
            
            if (empty($data['openid'])) {
                return ['code' => 0, 'msg' => '获取用户openid失败'];
            }
            
            return [
                'code' => 1,
                'msg' => '获取用户信息成功',
                'data' => [
                    'openid' => $data['openid'],
                    'session_key' => $data['session_key'] ?? '',
                    'unionid' => $data['unionid'] ?? ''
                ]
            ];
            
        } catch (\Exception $e) {
            return ['code' => 0, 'msg' => '微信服务异常：' . $e->getMessage()];
        }
    }
    
    /**
     * 解密用户数据
     * @author 王勇程 <laughskydragon@qq.com>
     */
    private function decryptData($sessionKey, $encryptedData, $iv)
    {
        try {
            $aesKey = base64_decode($sessionKey);
            $aesIV = base64_decode($iv);
            $aesCipher = base64_decode($encryptedData);
            
            $result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
            $dataObj = json_decode($result, true);
            
            if ($dataObj == null) {
                return ['code' => 0, 'msg' => '数据解密失败'];
            }
            
            $appid = config('wechat.appid');
            if ($dataObj['watermark']['appid'] != $appid) {
                return ['code' => 0, 'msg' => 'appid校验失败'];
            }
            
            return ['code' => 1, 'msg' => '解密成功', 'data' => $dataObj];
            
        } catch (\Exception $e) {
            return ['code' => 0, 'msg' => '解密异常：' . $e->getMessage()];
        }
    }
    
    /**
     * HTTP GET请求
     * @author 王勇程 <laughskydragon@qq.com>
     */
    private function httpGet($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
}
